package com.mes.schedule.manager;

import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.mes.common.condition.ConditionObject;
import com.mes.common.condition.ConditionObjectLink;
import com.mes.common.condition.Conditions;
import com.mes.common.exception.bo.BaseBusinessException;
import com.mes.common.manager.BasicManager;
import com.mes.schedule.dao.DemandSTaskLinkDao;
import com.mes.schedule.dao.SPartTaskDao;
import com.mes.schedule.domain.DemandSTaskLink;
import com.mes.schedule.domain.SPartTask;
import com.mes.schedule.domain.ScheduleScheme;
import com.mes.schedule.manager.iface.IDemandSTaskLinkManager;
import com.mes.schedule.util.ScheduleUtils;
import com.mes.task.dao.DemandDao;
import com.mes.task.domain.Demand;

@Component("demandSTaskLinkManager")
@Transactional
public class DemandSTaskLinkManager extends BasicManager implements IDemandSTaskLinkManager{

	private static final Log log = LogFactory
			.getLog(DemandSTaskLinkManager.class);

	 
	private DemandSTaskLinkDao demandSTaskLinkDao;
	 
	private SchedulePartTaskManager schedulePartTaskManager;
	 
	private SPartTaskDao sPartTaskDao;

	 
	private DemandDao demandDao;

	public DemandSTaskLinkDao getDemandSTaskLinkDao() {
		return demandSTaskLinkDao;
	}

	public void setDemandSTaskLinkDao(DemandSTaskLinkDao demandSTaskLinkDao) {
		this.basicDao = demandSTaskLinkDao;
		this.demandSTaskLinkDao = demandSTaskLinkDao;
	}

	public SchedulePartTaskManager getSchedulePartTaskManager() {
		return schedulePartTaskManager;
	}

	public void setSchedulePartTaskManager(
			SchedulePartTaskManager schedulePartTaskManager) {
		this.schedulePartTaskManager = schedulePartTaskManager;
	}

	@Deprecated
	public List<DemandSTaskLink> getAllEffectedLinks() {
		List demandSTaskLinkList = null;
		Conditions conditions = new Conditions();
		conditions.addCondition(new ConditionObjectLink("isInEffect",
				ConditionObject.EQUAL_OPERATOR, new Integer(
						DemandSTaskLink.ISINEFFECT_IS).toString(),
				ConditionObject.INTEGER_TYPE));
		try {
			demandSTaskLinkList = this.get(conditions);
		} catch (BaseBusinessException e) {
			e.printStackTrace();
		}
		return demandSTaskLinkList;
	}

	@Deprecated
	public List<DemandSTaskLink> getEffectedLinksByDemandUid(
			String scheduleUid, String demandUid) {
		List demandSTaskLinkList = null;
		Conditions conditions = new Conditions();
		conditions.addCondition(new ConditionObjectLink("isInEffect",
				ConditionObject.EQUAL_OPERATOR, new Integer(
						DemandSTaskLink.ISINEFFECT_IS).toString(),
				ConditionObject.INTEGER_TYPE));

		conditions.addCondition(new ConditionObjectLink("demandUid",
				ConditionObject.EQUAL_OPERATOR, demandUid,
				ConditionObject.STRING_TYPE));
		conditions.addCondition(new ConditionObjectLink("scheduleUid",
				ConditionObject.EQUAL_OPERATOR, scheduleUid,
				ConditionObject.STRING_TYPE));
		try {
			demandSTaskLinkList = this.get(conditions);
		} catch (BaseBusinessException e) {
			e.printStackTrace();
		}
		return demandSTaskLinkList;
	}

	public List<DemandSTaskLink> getRelativeDemandTaskLinks(SPartTask spartTask) {
		return this.getEffectedLinksByTaskUid(spartTask.getScheduleUid(),
				spartTask.getTaskUid());
	}

	 
	public Boolean add(Serializable object) throws BaseBusinessException {
		DemandSTaskLink demandTaskLink = (DemandSTaskLink) object;
		if (demandTaskLink.getLockLevel() == null) {
			// 缺省为非锁定
			demandTaskLink.setLockLevel(0);
		}

		if (demandTaskLink.getIsInEffect() == null) {
			// 缺省为有效
			demandTaskLink.setIsInEffect(1);
		}
		String partTaskUid = demandTaskLink.getPartTaskUid();
		List<String> taskuids = new Vector<String>();
		taskuids.add(partTaskUid);
		Boolean result = this.add(object);
		this.updatePlanInfo(demandTaskLink.getScheduleUid(), taskuids);
		return result;
	}

	 
	public Boolean update(Serializable object) throws BaseBusinessException {
		DemandSTaskLink demandTaskLink = (DemandSTaskLink) object;
		String partTaskUid = demandTaskLink.getPartTaskUid();
		List<String> taskuids = new Vector<String>();
		taskuids.add(partTaskUid);
		Boolean result = this.update(object);
		this.updatePlanInfo(demandTaskLink.getScheduleUid(), taskuids);
		return result;
	}

	 
	public Boolean delete(Serializable object) throws BaseBusinessException {
		DemandSTaskLink demandSTaskLink = (DemandSTaskLink) object;
		String partTaskUid = demandSTaskLink.getPartTaskUid();
		List<String> taskuids = new Vector<String>();
		taskuids.add(partTaskUid);
		Boolean result = this.delete(object);
		this.updatePlanInfo(demandSTaskLink.getScheduleUid(), taskuids);
		return result;
	}

	private void updatePlanInfo(String scheduleUid, List<String> taskuids) {
		ScheduleScheme scheduleScheme = ScheduleUtils
				.getScheduleScheme(scheduleUid);
		for (String taskuid : taskuids) {
			try {
				SPartTask partTask = (SPartTask) scheduleScheme
						.getAllPartTaskMap().get(taskuid);
				if (partTask != null)
					this.updatePlanInfo(partTask);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	 
	public void deleteUnLockedLinks(String scheduleUid, String masterShopUid)
			throws Exception {
		// TODO Auto-generated method stub
		List<DemandSTaskLink> links = this.demandSTaskLinkDao
				.getUnLockedLinks(masterShopUid);
		this.delete(links);

	}

	public DemandDao getDemandDao() {
		return demandDao;
	}

	public void setDemandDao(DemandDao demandDao) {
		this.demandDao = demandDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.mes.common.bo.AbstractManagerSupport#add(java.io.Serializable)
	 */

	 
	public List<DemandSTaskLink> getEffectedLinksByTaskUid(String scheduleUid,
			String taskUid) {
		List demandSTaskLinkList = null;
		Conditions conditions = new Conditions();
		conditions.addCondition(new ConditionObjectLink("partTaskUid",
				ConditionObject.EQUAL_OPERATOR, taskUid,
				ConditionObject.STRING_TYPE));
		conditions.addCondition(new ConditionObjectLink("scheduleUid",
				ConditionObject.EQUAL_OPERATOR, scheduleUid,
				ConditionObject.STRING_TYPE));
		conditions.addCondition(new ConditionObjectLink("isInEffect",
				ConditionObject.EQUAL_OPERATOR, "1",
				ConditionObject.INTEGER_TYPE));

		try {
			demandSTaskLinkList = this.get(conditions);
		} catch (BaseBusinessException e) {
			e.printStackTrace();
		}
		return demandSTaskLinkList;
	}

	 
	public void saveOrUpdateLink(DemandSTaskLink demandSTaskLink)
			throws BaseBusinessException {
		if (demandSTaskLink.getPartTaskUid() == null
				|| demandSTaskLink.getDemandUid() == null
				|| demandSTaskLink.getLinkQty() == null)
			throw new BaseBusinessException("指令与任务链接信息不完整");

		DemandSTaskLink oDemandTaskLink = this.demandSTaskLinkDao
				.getDemandTaskLink(demandSTaskLink.getScheduleUid(),
						demandSTaskLink.getDemandUid(), demandSTaskLink
								.getPartTaskUid());

		if (oDemandTaskLink == null) {
			this.add(demandSTaskLink);
		} else {
			if (oDemandTaskLink.getIsInEffect() != null
					&& oDemandTaskLink.getIsInEffect().equals(
							DemandSTaskLink.ISINEFFECT_IS)
					&& oDemandTaskLink.getLinkQty() != null
					&& !oDemandTaskLink.getLinkQty().equals(0)) {
				oDemandTaskLink.setLinkQty(demandSTaskLink.getLinkQty()
						+ oDemandTaskLink.getLinkQty());
			} else {
				oDemandTaskLink.setIsInEffect(DemandSTaskLink.ISINEFFECT_IS);
				oDemandTaskLink.setLinkQty(demandSTaskLink.getLinkQty());
			}
			this.update(oDemandTaskLink);
		}

	}

	 
	public void updatePlanInfo(SPartTask spartTask)
			throws Exception {
		try {

			List<DemandSTaskLink> links = this
					.getRelativeDemandTaskLinks(spartTask);
			if (links != null && links.size() > 0) {
				for (Iterator iterator2 = links.iterator(); iterator2.hasNext();) {
					DemandSTaskLink link = (DemandSTaskLink) iterator2.next();
					if (link.getDemand() == null && link.getDemandUid() != null) {
						Demand demand = (Demand) this.demandDao.getById(link
								.getDemandUid());
						link.setDemand(demand);
					}
				}
				// 取最紧急任务的交货期与优先级
				Collections.sort(links, new Comparator<DemandSTaskLink>() {

					public int compare(DemandSTaskLink link1,
							DemandSTaskLink link2) {

						if (link1.getDemand().getLateFinish() == null)
							return 1;
						if (link2.getDemand().getLateFinish() == null)
							return -1;

						if (link1.getDemand().getLateFinish().getTime() < link2
								.getDemand().getLateFinish().getTime()) {
							return -1;
						} else {
							return 1;
						}
					}
				});

				Demand decideDemand = links.get(0).getDemand();
				if (decideDemand != null) {
					spartTask.setLateFinish(decideDemand.getLateFinish());
					spartTask.setIsCritical(decideDemand.getIsCritical().intValue());
				}
			} else {
				spartTask.setLateFinish(null);
				spartTask.setIsCritical(0);
			}

			schedulePartTaskManager.update(spartTask);
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new BaseBusinessException(e.getMessage());
		}

	}

	 
	public void deleteUnlockLinksByDemandUid(String scheduleUid,
			String demandUid) {
		try {
			List<DemandSTaskLink> links = this.demandSTaskLinkDao
					.getDemandTaskLinksByDemand(scheduleUid, demandUid, null);
			if (links != null && links.size() > 0) {
				for (DemandSTaskLink link : links) {
					if (link.getLockLevel() == null
							|| link.getLockLevel().equals(0))
						this.delete(link);
				}
			}

		} catch (BaseBusinessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	 
	public void deleteLinksByDemandUid(String scheduleUid, String demandUid) throws Exception {
		try {
			List<DemandSTaskLink> links = this.demandSTaskLinkDao
					.getDemandTaskLinksByDemand(scheduleUid, demandUid, null);
			this.delete(links);
			Demand d = this.demandDao.getById(demandUid);
			//d.setArrangeQty(0d);
		} catch (BaseBusinessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	 
	public void deleteLinksByTaskUid(String scheduleUid, String taskUid) throws Exception {
		try {
			List<DemandSTaskLink> links = this.demandSTaskLinkDao
					.getDemandTaskLinksByTask(scheduleUid, taskUid);
			this.delete(links);
		} catch (BaseBusinessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	 
	public void taskQtyChange(SPartTask spartTask) throws BaseBusinessException {
		// TODO Auto-generated method stub
		// 重新更新指令链接数量
		// 如果链接数量 大于 其在制数量，则应该一次扣除

		if (spartTask.getDemandLinkQty() != null
				&& spartTask.getDemandLinkQty() > spartTask.getPlanQty()) {

			List<DemandSTaskLink> demandSTaskLinks = this.demandSTaskLinkDao
					.getEffectiveLinksByTask(spartTask.getScheduleUid(),
							spartTask.getTaskUid());
			if (demandSTaskLinks != null && demandSTaskLinks.size() > 0) {
				// 按照升序进行排列
				Collections.sort(demandSTaskLinks,
						new Comparator<DemandSTaskLink>() {
							public int compare(DemandSTaskLink d1,
									DemandSTaskLink d2) {
								if (d1.getDemand().getLateFinish() == null)
									return -1;
								if (d2.getDemand().getLateFinish() == null)
									return 1;
								return d2.getDemand().getLateFinish()
										.compareTo(
												d1.getDemand().getLateFinish());

							}
						});

				double remainQty = spartTask.getDemandLinkQty()
						- spartTask.getPlanQty();
				for (DemandSTaskLink demandTaskLink : demandSTaskLinks) {
					if (demandTaskLink.getLinkQty() > remainQty) {
						demandTaskLink.setLinkQty(demandTaskLink.getLinkQty()
								- remainQty);
						this.update(demandTaskLink);
						break;
					} else {
						remainQty -= demandTaskLink.getLinkQty();
						this.delete(demandTaskLink);
					}
				}
			}
		}

	}

	 
	public void calDemandPlanInfo(String scheduleUid, Demand demand) {
		String demandUid = demand.getDemandUid();
		if (log.isDebugEnabled()) {
			if (demandUid.equals("d3a5f17a-2bc2-4805-b4b0-aaf49e7fa5be")) {
				log.debug(demandUid);
			}
		}
		float arrangeQty = 0;
		Date planFinish = null;
		List<DemandSTaskLink> list = this.demandSTaskLinkDao
				.getDemandTaskLinksByDemand(scheduleUid, demandUid, null);
		if (list != null && !list.isEmpty()) {
			for (DemandSTaskLink link : list) {
				arrangeQty += link.getLinkQty();
				// lqm todo
				SPartTask partTask = this.schedulePartTaskManager
						.getSchedulePartTask(scheduleUid, link.getPartTaskUid());

				if (partTask != null && partTask.getPlanFinish() != null) {
					if (planFinish == null
							|| partTask.getPlanFinish().after(planFinish))
						planFinish = partTask.getPlanFinish();
				}

			}
		}

		demand.setPlanFinish(planFinish);
		//demand.setArrangeQty((double)arrangeQty);

	}

	// 建立匹配关系的基本方法
	 
	public void autoCreateLink(String scheduleUid, Demand demandTemp)
			throws BaseBusinessException {

		float arrangeQty = (float) demandDao.getArrangeQty(demandTemp
				.getDemandUid(), scheduleUid);
//		demandTemp.setArrangeQty((double)arrangeQty);
		Date planFinish = demandDao.getPlanFinish(demandTemp.getDemandUid(),
				scheduleUid);
		demandTemp.setPlanFinish(planFinish);

		double remainQty = this.demandDao.getRemainQty(demandTemp
				.getDemandUid(), scheduleUid);
//		demandTemp.setRemainQty(remainQty);

		// 稳妥初始化已安排数量，为了保险
//		demandTemp.setArrangeQty((double)this.calArrangeQty(scheduleUid, demandTemp));

		// 指令需求数与指令已安排数量比较
		if (demandTemp.getDueQty() == null) {

			throw new BaseBusinessException("指令需求数量为空，请检查指令");
		}
		if (demandTemp.getDueQty() - demandTemp.getArrangeQty() == 0)
			return;// 已经全部安排

		List<SPartTask> partTasks = new Vector<SPartTask>();
		String partUid = demandTemp.getPartUid();

		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);

		// add by zy
		// 两种取零件任务的区别？ 这里没有发现区别
		for (SPartTask partTask : scheme.getSchedulePartTasks()) {
			// for (SPartTask partTask : scheme.getAllPartTaskMap().values()) {
			if (partTask.getPartUid().equals(partUid)) {
				partTasks.add(partTask);
			}
		}

		/**
		 * 对operationid为0的情况进行检查
		 */
		// by lqm
		for (SPartTask partTask : partTasks) {
			// 稳妥初始化已链接数量
			partTask.setDemandLinkQty((Double) calDemandLinkQty(partTask));
			partTask.getCurrentOperation();
			if (partTask.getCurrentOperation() == null)
				log.warn(partTask.getCurrentOperation());

		}

		Collections.sort(partTasks, new Comparator<SPartTask>() {
			public int compare(SPartTask partTask1, SPartTask partTask2) {
				if (partTask1.getCurrentOperation() == null
						&& partTask2.getCurrentOperation() == null) {
					return 0;
				} else if (partTask1.getCurrentOperation() == null) {
					return 1;
				} else if (partTask2.getCurrentOperation() == null) {
					return -1;
				}
				if (partTask2.getCurrentOperation().getOperationId() > (partTask1
						.getCurrentOperation().getOperationId()))
					return 1;
				else if (partTask2.getCurrentOperation().getOperationId()
						.equals(
								partTask1.getCurrentOperation()
										.getOperationId()))
					return partTask1.getBatchNum().compareTo(
							partTask2.getBatchNum());// 工序号相等的用批次号
				else {
					return -1;
				}
			}
		});

		for (int j = 0; j < partTasks.size(); j++) {
			SPartTask partTaskTemp = partTasks.get(j);

			// 指令需求数与指令已安排数量比较
			double demandRemainQty = demandTemp.getDueQty()
					- demandTemp.getArrangeQty();
			double partAvailableQty = partTaskTemp.getPlanQty()
					- partTaskTemp.getDemandLinkQty();
			if (demandRemainQty <= 0) {
				break;
			}
			// 任务计划数量和任务已经链接的数量比较
			if (partAvailableQty <= 0) {
				continue;
			}

			if (demandRemainQty <= partAvailableQty) {
				DemandSTaskLink demandTaskLink = new DemandSTaskLink();
				demandTaskLink.setDemandUid(demandTemp.getUuid());
				demandTaskLink.setPartTaskUid(partTaskTemp.getUuid());
				demandTaskLink.setIsInEffect(1);
				demandTaskLink.setLinkQty(demandRemainQty);
				demandTaskLink.setLockLevel(0);
				demandTaskLink.setDependType("1");
				demandTaskLink.setPartTask(partTaskTemp);
				demandTaskLink.setScheduleUid(scheduleUid);
				demandTemp.setArrangeQty(demandTemp.getDueQty());
				partTaskTemp.setDemandLinkQty(partTaskTemp.getDemandLinkQty()
						+ demandRemainQty);
				try {
					this.saveOrUpdateLink(demandTaskLink);

				} catch (BaseBusinessException e) {
					e.printStackTrace();
				}

				break;
			} else {
				DemandSTaskLink demandTaskLink = new DemandSTaskLink();
				demandTaskLink.setDemandUid(demandTemp.getUuid());
				demandTaskLink.setPartTaskUid(partTaskTemp.getUuid());
				demandTaskLink.setIsInEffect(1);
				demandTaskLink.setLinkQty(partAvailableQty);
				demandTaskLink.setLockLevel(0);
				demandTaskLink.setDependType("1");
				demandTaskLink.setPartTask(partTaskTemp);
				demandTaskLink.setScheduleUid(scheduleUid);
				demandTemp.setArrangeQty(demandTemp.getArrangeQty()
						+ (float) partAvailableQty);

				partTaskTemp.setDemandLinkQty(partTaskTemp.getPlanQty()
						.doubleValue());

				// 添加link是会自动进行判断

				try {
					this.saveOrUpdateLink(demandTaskLink);

				} catch (BaseBusinessException e) {
					e.printStackTrace();
				}
			}
		}

	}

	public double calDemandLinkQty(SPartTask partTask) {
		// TODO Auto-generated method stub
		double sum = 0d;
		List<DemandSTaskLink> links = this.getEffectedLinksByTaskUid(partTask
				.getScheme().getScheduleUid(), partTask.getTaskUid());

		if (links != null && links.size() > 0) {
			for (DemandSTaskLink link : links) {
				sum += link.getLinkQty();
			}
		}

		return sum;
	}

	 
	public float calArrangeQty(String scheduleUid, Demand demand) {
		// TODO Auto-generated method stub
		float sum = 0f;
		List<DemandSTaskLink> links = this.getEffectedLinksByDemandUid(
				scheduleUid, demand.getUuid());
		if (demand.getDeliveryQty() != null)
			sum = demand.getDeliveryQty().floatValue();// 先加上已交付数量
		if (links != null && links.size() > 0) {
			for (DemandSTaskLink link : links) {
				sum += link.getLinkQty();
			}
		}
		return sum;
	}
	
	/**
	 * @author lcs
	 * @see 原来是AbstractManagerSupport中的方暂时写成空方法，后买呢再改
	 * @param conditions
	 * @return
	 * @throws BaseBusinessException
	 */
	@SuppressWarnings("unchecked")
	public List get(Conditions conditions)  {
	
			return null;
		
	}

}
